﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using System.Diagnostics;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using CoreAudioApi;
using iTunesLib;

namespace ProgramController
{
    public class program_controller
    {
        public program_controller()
        {
            event_list = new List<Event>();
            event_list.Add(new Event_volumecontrol("Toggle Mute", 1));
            event_list.Add(new Event_volumecontrol("Raise Volume", 2));
            event_list.Add(new Event_volumecontrol("Lower Volume", 3));
            event_list.Add(new Event_volumecontrol("Max Volume", 4));
            //event_list.Add(new Event_launcher_closer("open_facebook", "http:\\www.facebook.com", 1));

            //event_list.Add(new Event_sendkeystroke("open_new_tab_in_firefox", "firefox", "^t"));

            event_list.Add(new Event_iTunesController("iTunes Next Track",1));
            event_list.Add(new Event_iTunesController("iTunes Previous Track", 2));
            event_list.Add(new Event_iTunesController("iTunes Play", 3));
            event_list.Add(new Event_iTunesController("iTunes Pause", 4));
            event_list.Add(new Event_iTunesController("iTunes Stop", 5));
            event_list.Add(new Event_iTunesController("iTunes Toggle Mute", 6));
            //add in some default events

        }

        private List<Event> event_list;

        // returns 1 if addition succeds, 0 if it fails
        public int add_event1(string event_name,  string data, int type)
        {
            Event_launcher_closer temp = new Event_launcher_closer(event_name, data, type);
            event_list.Add(temp);

            return 1;
        }

        public int add_event2(string event_name, string program_name, string key)
        {
            event_list.Add(new Event_sendkeystroke(event_name, program_name, key));

            return 1;
        }

        // return -1 if event cannot be found, return 1 if event is successfully deleted
        public int delete_event(string name_of_event)
        {
            int value = -1;
            for (int i = 0; i < event_list.Count(); i++)
            {
                if (event_list[i].event_name == name_of_event)
                {
                    event_list.RemoveAt(i);
                    value = 1;
                    break;
                }
            }
            return value;
        }

        public List<String> list_events()
        {
            List<String> temp = new List<String>();
            for (int i = 0; i < event_list.Count(); i++)
            {
                temp.Add(event_list[i].event_name);
            }
            return temp;
        }

        // returns -1 if event is not found, 0 if event failed, 1 if even succeeded
        public int activate_event(string name_of_event)
        {
            int value = -1;
            for (int i = 0; i < event_list.Count(); i++)
            {
                if (event_list[i].event_name == name_of_event)
                {
                    value = event_list[i].activate();
                }
            }

            return value;
        }

        private class Event
        {
            public string event_name;
            public int type;
            /* type=1 -> opens or closee new programs, opens new webpages 
             * type=2 -> controls volume
             * type=3 -> sends key strokes to a program
             * type 4 -> handles iTunes things
             * */

            public virtual int activate() { return 0; }

        }

        private class Event_launcher_closer : Event
        {
            public Event_launcher_closer(string e_name, string str, int foo)
            {
                event_name = e_name;
                destination = str;
                type = foo;
            }

            private string destination;

            //type=1 : open a program or website
            //type=2 : close a program
            public override int activate()
            {
                if (type == 1)
                {
                    System.Diagnostics.Process.Start(destination);
                }
                else if (type == 2)
                {
                    Process[] processes = Process.GetProcessesByName(destination);
                    foreach (Process p in processes)
                    {
                        IntPtr pFoundWindow = p.MainWindowHandle;
                        p.CloseMainWindow();
                    }
                }
                return 1;
            }
        }

        private class Event_volumecontrol : Event
        {
            /* type=1 : toggle mute on default audio device
             * type=2 : raise volume
             * type=3 : lower volume
             * type=4 : raise to max volume
             * */
            public Event_volumecontrol(string e_name, int event_type)
            {
                event_name = e_name;
                type = event_type;
            }

            public override int activate()
            {

                switch (type)
                {
                    case 1:
                        mute_volume();
                        break;
                    case 2:
                        raise_volume();
                        break;
                    case 3:
                        lower_volume();
                        break;
                    case 4:
                        raise_volume_to_max();
                        break;
                    default:
                        return 0;
                }

                return 1;
            }

            //private MMDevice device;

            private void mute_volume()
            {
                MMDeviceEnumerator devEnum = new MMDeviceEnumerator();
                MMDevice defaultDevice = devEnum.GetDefaultAudioEndpoint(EDataFlow.eRender, ERole.eMultimedia);
                defaultDevice.AudioEndpointVolume.Mute = !defaultDevice.AudioEndpointVolume.Mute;
                defaultDevice.AudioEndpointVolume.VolumeStepUp();
            }

            private void raise_volume()
            {
                MMDeviceEnumerator devEnum = new MMDeviceEnumerator();
                MMDevice defaultDevice = devEnum.GetDefaultAudioEndpoint(EDataFlow.eRender, ERole.eMultimedia);



                float curvold = defaultDevice.AudioEndpointVolume.MasterVolumeLevelScalar + 0.2f;
                if (curvold > 1) curvold = 1;
                defaultDevice.AudioEndpointVolume.MasterVolumeLevelScalar = curvold;
            }

            private void lower_volume()
            {
                MMDeviceEnumerator devEnum = new MMDeviceEnumerator();
                MMDevice defaultDevice = devEnum.GetDefaultAudioEndpoint(EDataFlow.eRender, ERole.eMultimedia);

                float curvold = defaultDevice.AudioEndpointVolume.MasterVolumeLevelScalar - 0.2f;
                if (curvold > 1) curvold = 1;
                if (curvold < 0) curvold = 0;
                defaultDevice.AudioEndpointVolume.MasterVolumeLevelScalar = curvold;
            }

            private void raise_volume_to_max()
            {
                MMDeviceEnumerator devEnum = new MMDeviceEnumerator();
                MMDevice defaultDevice = devEnum.GetDefaultAudioEndpoint(EDataFlow.eRender, ERole.eMultimedia);

                defaultDevice.AudioEndpointVolume.MasterVolumeLevelScalar = 1f;
            }
        }

        private class Event_sendkeystroke : Event
        {
            public Event_sendkeystroke(string e_name, string pname, string key)
            {
                event_name = e_name;
                program_name = pname;
                key_to_send = key;
            }

            string key_to_send;
            string program_name;

            [DllImport("USER32.DLL", CharSet = CharSet.Unicode)]
            public static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
            [DllImport("USER32.DLL")]
            public static extern Boolean SetForegroundWindow(IntPtr hWnd);

            public override int activate()
            {
                /*IntPtr windowHandle = FindWindow("CalcFrame", "Calculator");
                 if (windowHandle == IntPtr.Zero)
                 {
                     // this program isn't running
                     return 0;
                 }
                 SetForegroundWindow(windowHandle);
                 SendKeys.SendWait(key_to_send);*/

                //Process[] localAll = Process.GetProcesses();
                Process[] processes = Process.GetProcessesByName(program_name);
                foreach (Process p in processes)
                {
                    IntPtr pFoundWindow = p.MainWindowHandle;
                    SetForegroundWindow(pFoundWindow);
                    SendKeys.SendWait(key_to_send);
                    //p.CloseMainWindow();
                    //p.StandardInput.WriteLine("test");

                }

                return 1;
            }
        }

        private class Event_iTunesController : Event
        {
            public Event_iTunesController(string e_name, int foo)
            {
                event_name = e_name;
                type = foo;
            }

            delegate void Router(object arg);
            iTunesApp iTunes = new iTunesAppClass();

            public override int activate()
            {
                switch (type)
                {
                    case 1:
                        iTunes.NextTrack();
                        break;
                    case 2:
                        iTunes.PreviousTrack();
                        break;
                    case 3:
                        iTunes.Play();
                        break;
                    case 4:
                        iTunes.Pause();
                        break;
                    case 5:
                        iTunes.Stop();
                        break;
                    case 6:
                        iTunes.Mute = !iTunes.Mute;
                        break;
                    default:
                        return 0;
                }
                
                return 1;
            }

        }

        private class Event_windowscontroller : Event
        {
            public Event_windowscontroller()
            {

            }

            public override int activate()
            {



                return 1;
            }

        }
    }
}
